# app.py
import httpx
import os
import json
from collections import defaultdict
import smtplib
from datetime import datetime, timedelta
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
from filelock import FileLock
from dotenv import load_dotenv
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from flask import Flask, request, session, redirect, url_for, render_template, jsonify  # 添加 jsonify 导入
from models.database import init_db, SessionLocal, engine
from models.order import Base, Order, StatusHistory, SyncLog
from models.user import User
from controllers.order_controller import OrderController
from controllers.customer_controller import CustomerController
from controllers.api_controller import APIController
from controllers.user_controller import UserController  # 添加用户控制器
from services.order_service import get_country_name, format_phone_number, format_phone_number_without_prefix
from config import SITES
from werkzeug.security import generate_password_hash
from controllers.user_auth import requires_auth, requires_role  # 添加导入

# 加载环境变量
load_dotenv()

# 同步状态文件路径
LAST_SYNC_FILE = "last_sync.txt"
LOCK_FILE = "database.db.lock"
MAX_RETRIES = 3
LOG_FILE = "sync.log"
DINGTALK_WEBHOOK = os.getenv("DINGTALK_WEBHOOK")
DINGTALK_SECRET = os.getenv("DINGTALK_SECRET")  # 添加钉钉签名密钥

# 定义需要发送告警的状态
ALERT_STATUSES = ['processing', 'on-hold', 'cancelled', 'refunded', 'failed']

def log(message):
    """记录日志"""
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    log_message = f"[{timestamp}] {message}"
    print(log_message)
    
    # 同时写入日志文件
    try:
        with open(LOG_FILE, "a", encoding="utf-8") as f:
            f.write(log_message + "\n")
    except Exception as e:
        print(f"写入日志文件失败: {e}")

def send_dingtalk_notification(title, content):
    if not DINGTALK_WEBHOOK:
        return
    try:
        import time
        import hmac
        import hashlib
        import base64
        import urllib.parse
        
        # 构建请求参数
        payload = {
            "msgtype": "text",
            "text": {
                "content": f"{title}\n```\n{content}\n```"
            }
        }
        
        # 如果配置了签名密钥，则添加签名
        if DINGTALK_SECRET:
            timestamp = str(round(time.time() * 1000))
            secret_enc = DINGTALK_SECRET.encode('utf-8')
            string_to_sign = '{}\n{}'.format(timestamp, DINGTALK_SECRET)
            string_to_sign_enc = string_to_sign.encode('utf-8')
            hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()
            sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
            
            # 构建带签名的URL
            url = f"{DINGTALK_WEBHOOK}&timestamp={timestamp}&sign={sign}"
        else:
            url = DINGTALK_WEBHOOK
        
        # 创建 httpx 客户端
        with httpx.Client(timeout=5.0) as client:
            client.post(
                url,
                json=payload
            )
    except Exception as e:
        log(f"❌ 钉钉通知发送失败: {e}")

def send_email_alert(subject, body):
    if not SMTP_CONFIG["user"] or not NOTIFY_EMAILS:
        return
    msg = MIMEMultipart()
    msg["From"] = SMTP_CONFIG["user"]
    msg["To"] = ", ".join(NOTIFY_EMAILS)
    msg["Subject"] = EMAIL_SUBJECT_PREFIX + subject
    msg.attach(MIMEText(body, "html"))
    try:
        server = smtplib.SMTP(SMTP_CONFIG["host"], SMTP_CONFIG["port"])
        server.starttls()
        server.login(SMTP_CONFIG["user"], SMTP_CONFIG["password"])
        server.sendmail(SMTP_CONFIG["user"], NOTIFY_EMAILS, msg.as_string())
        server.quit()
        log("📧 邮件告警已发送")
    except Exception as e:
        log(f"❌ 邮件发送失败: {e}")

def fetch_woo_orders(client: httpx.Client, site: dict, params: dict):
    url = f"{site['url']}/wp-json/wc/v3/orders"
    
    # 添加浏览器模拟的请求头
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
        "Accept-Language": "en-US,en;q=0.9",
        "Accept-Encoding": "gzip, deflate, br",
        "Connection": "keep-alive",
        "Upgrade-Insecure-Requests": "1",
        "Sec-Fetch-Dest": "document",
        "Sec-Fetch-Mode": "navigate",
        "Sec-Fetch-Site": "none",
        "Cache-Control": "max-age=0",
        "Referer": site['url'],
        "Accept-Charset": "utf-8"
    }
    
    try:
        response = client.get(
            url,
            params=params,
            auth=(site["consumer_key"], site["consumer_secret"]),
            headers=headers  # 添加请求头
        )
        response.raise_for_status()
        
        # 检查响应内容是否为空
        if not response.content:
            raise ValueError("API响应为空")
        
        # 检查是否被Cloudflare拦截
        content_str = response.text.strip()
        if "cloudflare" in content_str.lower() and ("challenge" in content_str.lower() or "just a moment" in content_str.lower()):
            log(f"❌ 请求被Cloudflare拦截: {content_str[:300]}...")
            raise ValueError("请求被Cloudflare安全防护拦截，请稍后重试或联系站点管理员")
        
        # 检查响应内容是否包含HTML/PHP错误信息
        if content_str.startswith("<") or "Warning" in content_str or "Fatal error" in content_str:
            log(f"❌ API返回了错误信息而不是JSON数据: {content_str[:200]}...")
            raise ValueError("API返回了错误信息而不是JSON数据")
        
        return response.json()
    except httpx.RequestError as e:
        log(f"❌ 网络请求错误: {e}")
        raise
    except httpx.HTTPStatusError as e:
        # 特别处理403错误
        if e.response.status_code == 403:
            content_str = e.response.text.strip()
            if "cloudflare" in content_str.lower():
                log(f"❌ Cloudflare拦截 (403): {content_str[:200]}...")
                raise ValueError("请求被Cloudflare安全防护拦截，请稍后重试或联系站点管理员")
            else:
                log(f"❌ HTTP 403 Forbidden: {content_str[:200]}...")
                raise ValueError("API访问被拒绝，请检查API密钥和权限设置")
        else:
            log(f"❌ HTTP状态错误: {e.response.status_code} - {e.response.text[:200]}...")
            raise

@retry(
    stop=stop_after_attempt(3),
    wait=wait_exponential(multiplier=1, min=4, max=10),
    retry=retry_if_exception_type((httpx.RequestError, ValueError)),
    reraise=True
)
def fetch_woo_orders_with_retry(client: httpx.Client, site: dict, params: dict):
    """带重试机制的获取WooCommerce订单函数"""
    return fetch_woo_orders(client, site, params)

def get_bing_daily_image():
    """获取Bing每日一图"""
    try:
        # Bing每日一图API
        url = "https://www.bing.com/HPImageArchive.aspx"
        params = {
            "format": "js",
            "idx": 0,  # 0表示今天，1表示昨天，以此类推
            "n": 1,    # 获取图片数量
            "mkt": "zh-CN"  # 市场代码，可以改为en-US等
        }
        
        # 创建 httpx 客户端
        with httpx.Client(timeout=10.0) as client:
            response = client.get(url, params=params)
        response.raise_for_status()
        
        data = response.json()
        if "images" in data and len(data["images"]) > 0:
            image = data["images"][0]
            # 构造完整的图片URL
            image_url = "https://www.bing.com" + image["url"]
            return image_url
        
        return None
    except Exception as e:
        print(f"获取Bing每日一图失败: {e}")
        return None

def sync_all():
    log("🚀 开始同步所有站点")
    results = []
    sync_stats = {"inserted": 0, "updated": 0, "total": 0}  # 添加统计信息
    lock = FileLock(LOCK_FILE, timeout=30)
    
    with lock:
        db = SessionLocal()
        try:
            for site in SITES:
                log(f"🔄 同步 {site['user']}")
                success = False
                alert_events = []
                site_stats = {"inserted": 0, "updated": 0, "total": 0}  # 站点统计
                try:
                    # 移除时间限制，获取所有订单
                    params = {"per_page": 100, "page": 1, "status": "any"}
                    
                    # 创建带有浏览器模拟设置的客户端
                    with httpx.Client(
                        timeout=30.0,  # 增加超时时间
                        http2=True,
                        follow_redirects=True,  # 跟随重定向
                        headers={
                            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
                            "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
                            "Accept-Language": "en-US,en;q=0.9",
                            "Accept-Encoding": "gzip, deflate, br",
                            "Connection": "keep-alive",
                            "Upgrade-Insecure-Requests": "1",
                            "Sec-Fetch-Dest": "document",
                            "Sec-Fetch-Mode": "navigate",
                            "Sec-Fetch-Site": "none",
                            "Cache-Control": "max-age=0"
                        }
                    ) as client:
                        all_orders = []
                        page = 1
                        max_retries = 3
                        retry_count = 0
                        
                        while True:
                            try:
                                params["page"] = page
                                orders = fetch_woo_orders_with_retry(client, site, params)
                                all_orders.extend(orders)
                                
                                # 检查是否有更多页面
                                if len(orders) < params["per_page"]:
                                    break
                                
                                page += 1
                                retry_count = 0  # 重置重试计数
                                
                                # 为了避免API限制，添加短暂延迟
                                import time
                                time.sleep(0.5)
                            except ValueError as e:
                                if "cloudflare" in str(e).lower() or "拦截" in str(e):
                                    retry_count += 1
                                    if retry_count <= max_retries:
                                        log(f"⚠️ Cloudflare拦截，第{retry_count}次重试...")
                                        import time
                                        time.sleep(2 ** retry_count)  # 指数退避
                                        continue
                                    else:
                                        error_msg = f"多次尝试后仍被Cloudflare拦截: {str(e)}"
                                        log(f"❌ {error_msg}")
                                        results.append(f"🚨 {site['user']} {error_msg}")
                                        # 跳过这个站点
                                        break
                                elif "API返回了错误信息而不是JSON数据" in str(e):
                                    error_msg = f"API返回错误信息，跳过站点 {site['user']}"
                                    log(f"❌ {error_msg}")
                                    results.append(f"🚨 {site['user']} {error_msg}")
                                    # 跳过这个站点
                                    break
                                else:
                                    # 重新抛出其他ValueError异常
                                    raise
                            except httpx.RequestError as e:
                                retry_count += 1
                                if retry_count <= max_retries:
                                    log(f"⚠️ 网络请求错误，第{retry_count}次重试: {str(e)}")
                                    import time
                                    time.sleep(2 ** retry_count)  # 指数退避
                                    continue
                                else:
                                    error_msg = f"多次尝试后网络请求仍失败: {str(e)}"
                                    log(f"❌ {error_msg}")
                                    results.append(f"🚨 {site['user']} {error_msg}")
                                    # 跳过这个站点
                                    break

                    # 如果因为API错误跳过了站点，则继续下一个站点
                    if not all_orders and any("API返回错误信息" in r for r in results if site['user'] in r):
                        continue

                    inserted = updated = 0
                    for o in all_orders:
                        order_id = str(o["id"])
                        new_status = o["status"]
                        remote_modified = datetime.fromisoformat(o["date_modified_gmt"])
                        order_date = datetime.fromisoformat(o["date_created_gmt"])
                        billing = o.get("billing", {})
                        # 分别获取名和姓
                        customer_first_name = billing.get('first_name', '')
                        customer_last_name = billing.get('last_name', '')
                        # 组合完整姓名
                        customer = (f"{customer_first_name} {customer_last_name}").strip() or billing.get("company", "Unknown")
                        # 获取新字段信息
                        customer_country = billing.get("country", "")
                        customer_email = billing.get("email", "")
                        customer_phone = billing.get("phone", "")
                        # 获取完整地址信息
                        customer_address_1 = billing.get("address_1", "")
                        customer_address_2 = billing.get("address_2", "")
                        customer_city = billing.get("city", "")
                        customer_state = billing.get("state", "")
                        customer_postcode = billing.get("postcode", "")
                        
                        # 获取物流信息
                        meta_data = o.get("meta_data", [])
                        tracking_number = ""
                        
                        # 首先检查订单级别的物流信息
                        for meta in meta_data:
                            # 支持多种物流单号字段
                            if meta.get("key") in ["_tracking_number", "tracking_number", "_wc_order_tracking_number"]:
                                tracking_number = meta.get("value", "")
                                break
                        
                        # 如果没有找到订单级别的物流信息，检查订单项目的物流信息
                        if not tracking_number:
                            # 检查line_items中的物流信息
                            line_items = o.get("line_items", [])
                            for item in line_items:
                                item_meta_data = item.get("meta_data", [])
                                for meta in item_meta_data:
                                    # 检查是否有物流信息存储在订单项目中
                                    if meta.get("key") == "_vi_wot_order_item_tracking_data":
                                        try:
                                            tracking_data = json.loads(meta.get("value", "[]"))
                                            if tracking_data and isinstance(tracking_data, list) and len(tracking_data) > 0:
                                                # 使用第一个物流信息的单号
                                                tracking_number = tracking_data[0].get("tracking_number", "")
                                                break
                                        except:
                                            pass
                                if tracking_number:
                                    break
                        
                        # 如果仍然没有找到物流信息，检查shipping_lines中的物流信息
                        if not tracking_number:
                            shipping_lines = o.get("shipping_lines", [])
                            for shipping in shipping_lines:
                                shipping_meta_data = shipping.get("meta_data", [])
                                for meta in shipping_meta_data:
                                    # 支持shipping_tracking类型的物流信息
                                    if meta.get("key") == "tracking_number":
                                        tracking_number = meta.get("value", "")
                                        break
                                if tracking_number:
                                    break
                        
                        # 为物流信息创建标准格式
                        tracking_info = []
                        if tracking_number:
                            # 清理跟踪号码，只保留数字和字母
                            cleaned_number = ''.join(c for c in tracking_number if c.isalnum())
                            
                            # 根据物流单号特征识别承运商
                            carrier_slug = "unknown"
                            carrier_name = "Unknown"
                            carrier_url = ""
                            
                            # InPost: 24位纯数字
                            if len(cleaned_number) == 24 and cleaned_number.isdigit():
                                carrier_slug = "inpost"
                                carrier_name = "InPost"
                                carrier_url = "https://inpost.pl/sledzenie-przesylek?number={tracking_number}"
                            # DPD: 10-14位数字/字母组合
                            elif 10 <= len(cleaned_number) <= 14 and cleaned_number.isalnum():
                                carrier_slug = "dpd"
                                carrier_name = "DPD"
                                carrier_url = "https://tracktrace.dpd.com.pl/parcelDetails?typ=1&p1={tracking_number}"
                            else:
                                # 尝试通过其他方式识别承运商
                                # 检查是否有承运商信息在其他元数据中
                                carrier_name_meta = None
                                carrier_slug_meta = None
                                
                                # 检查订单级别的承运商信息
                                for meta in meta_data:
                                    if meta.get("key") == "_wc_order_tracking_carrier":
                                        carrier_name_meta = meta.get("value", "")
                                    elif meta.get("key") == "_wc_order_tracking_carrier_slug":
                                        carrier_slug_meta = meta.get("value", "")
                                
                                # 如果没有找到订单级别的承运商信息，检查shipping_lines中的承运商信息
                                if not carrier_name_meta:
                                    shipping_lines = o.get("shipping_lines", [])
                                    for shipping in shipping_lines:
                                        shipping_meta_data = shipping.get("meta_data", [])
                                        for meta in shipping_meta_data:
                                            if meta.get("key") == "carrier_name" or meta.get("key") == "shipping_carrier":
                                                carrier_name_meta = meta.get("value", "")
                                            elif meta.get("key") == "carrier_slug":
                                                carrier_slug_meta = meta.get("value", "")
                                        if carrier_name_meta:
                                            break
                                
                                if carrier_name_meta:
                                    carrier_name = carrier_name_meta
                                    carrier_slug = carrier_slug_meta or carrier_name_meta.lower()
                                    # 根据承运商名称生成URL
                                    if "inpost" in carrier_name.lower():
                                        carrier_url = "https://inpost.pl/sledzenie-przesylek?number={tracking_number}"
                                    elif "dpd" in carrier_name.lower():
                                        carrier_url = "https://tracktrace.dpd.com.pl/parcelDetails?typ=1&p1={tracking_number}"
                            
                            # 创建标准格式的物流信息
                            tracking_info.append({
                                "tracking_number": tracking_number,
                                "carrier_slug": carrier_slug,
                                "carrier_url": carrier_url,
                                "carrier_name": carrier_name,
                                "carrier_type": "custom-carrier",
                                "time": int(datetime.now().timestamp())  # 使用当前时间作为创建时间
                            })
                        
                        item_count = len(o.get("line_items", []))
                        item_total = float(o.get("total", 0)) - float(o.get("shipping_total", 0))
                        shipping_total = float(o.get("shipping_total", 0))
                        # 获取商品详情
                        line_items = o.get("line_items", [])
                        
                        # 如果有物流信息，将其添加到line_items中
                        if tracking_info:
                            # 创建一个虚拟的商品项来存储物流信息
                            tracking_item = {
                                "name": "物流信息",
                                "sku": "",
                                "quantity": 1,
                                "price": 0.0,
                                "total": 0.0,
                                "meta_data": [
                                    {
                                        "key": "_vi_wot_order_item_tracking_data",
                                        "value": json.dumps(tracking_info, ensure_ascii=False)
                                    }
                                ]
                            }
                            line_items.append(tracking_item)
                        
                        item_details = json.dumps(line_items, ensure_ascii=False)

                        existing = db.query(Order).filter(
                            Order.order_id == order_id,
                            Order.source == site["user"]  # 修复BUG：原来是site["name"]，应该是site["user"]
                        ).first()

                        if existing:
                            if existing.remote_modified and remote_modified <= existing.remote_modified:
                                continue
                            old_status = existing.status
                            if new_status != old_status:
                                db.add(StatusHistory(
                                    order_id=order_id,
                                    source=site["user"],  # 修复BUG：原来是site["name"]，应该是site["user"]
                                    old_status=old_status,
                                    new_status=new_status,
                                    changed_at=order_date  # 使用订单创建时间
                                ))
                                if new_status in ALERT_STATUSES:
                                    alert_events.append({
                                        "order_id": order_id,
                                        "source": site["user"],
                                        "old": old_status,
                                        "new": new_status,
                                        "customer": customer,
                                        "total": o["total"],
                                        "currency": o["currency"]
                                    })
                            existing.customer_first_name = customer_first_name
                            existing.customer_last_name = customer_last_name
                            existing.customer_name = customer
                            existing.customer_country = customer_country  # 更新国家信息
                            existing.customer_email = customer_email
                            existing.customer_phone = customer_phone
                            existing.customer_address = customer_address_1
                            existing.customer_address_2 = customer_address_2  # 保存第二地址
                            existing.customer_city = customer_city
                            existing.customer_state = customer_state
                            existing.customer_postcode = customer_postcode
                            existing.total = float(o["total"])
                            existing.currency = o["currency"]
                            existing.order_date = order_date
                            existing.status = new_status
                            existing.remote_modified = remote_modified
                            # 更新新字段
                            existing.item_count = item_count
                            existing.item_total = item_total
                            existing.shipping_total = shipping_total
                            existing.item_details = item_details  # 保存商品详情
                            updated += 1
                        else:
                            db.add(Order(
                                order_id=order_id,
                                source=site["user"],  # 修复BUG：原来是site["name"]，应该是site["user"]
                                domain=site["domain"],
                                customer_first_name=customer_first_name,
                                customer_last_name=customer_last_name,
                                customer_name=customer,
                                customer_country=customer_country,  # 添加国家信息
                                customer_email=customer_email,
                                customer_phone=customer_phone,
                                customer_address=customer_address_1,
                                customer_address_2=customer_address_2,  # 添加第二地址
                                customer_city=customer_city,
                                customer_state=customer_state,
                                customer_postcode=customer_postcode,
                                total=float(o["total"]),
                                currency=o["currency"],
                                order_date=order_date,
                                status=new_status,
                                remote_modified=remote_modified,
                                # 添加新字段
                                item_count=item_count,
                                item_total=item_total,
                                shipping_total=shipping_total,
                                item_details=item_details  # 保存商品详情
                            ))
                            
                            # 为新订单添加状态历史记录，使用订单创建时间
                            db.add(StatusHistory(
                                order_id=order_id,
                                source=site["user"],  # 修复BUG：原来是site["name"]，应该是site["user"]
                                old_status=None,
                                new_status=new_status,
                                changed_at=order_date  # 使用订单创建时间
                            ))
                            
                            inserted += 1

                    db.commit()
                    message = f"新增 {inserted}，更新 {updated}，总计 {len(all_orders)}"
                    log(f"✅ {message}")
                    results.append(f"✅ {site['user']} {message}")
                    success = True
                    
                    # 更新站点统计
                    site_stats["inserted"] = inserted
                    site_stats["updated"] = updated
                    site_stats["total"] = len(all_orders)
                    
                    # 更新总统计
                    sync_stats["inserted"] += inserted
                    sync_stats["updated"] += updated
                    sync_stats["total"] += len(all_orders)

                    if alert_events:
                        body = "<h2>⚠️ 订单状态变更告警</h2><ul>"
                        for ev in alert_events:
                            body += f"<li><strong>订单 {ev['order_id']}</strong> [{ev['source']}]<br>客户: {ev['customer']} | 金额: {ev['total']} {ev['currency']}<br>状态: <span style='color:red'>{ev['old']} → {ev['new']}</span></li>"
                        body += "</ul>"
                        send_email_alert("状态变更告警", body)

                except Exception as e:
                    error_msg = f"失败: {type(e).__name__}: {e}"
                    log(f"❌ {error_msg}")
                    results.append(f"🚨 {site['user']} {error_msg}")
                    db.rollback()
                finally:
                    db.add(SyncLog(site_name=site["user"], success=success, message=message if success else error_msg))
                    db.commit()

            summary = "\n".join(results)
            final_status = "✅ 全部成功" if all("✅" in r for r in results) else "⚠️ 部分失败"
            send_dingtalk_notification(f"订单同步 {final_status}", f"# 📡 报告\n{summary}")
            log(f"🏁 同步结束: {final_status}")
            
            # 返回同步统计信息
            return sync_stats

        finally:
            db.close()

def create_app():
    """创建Flask应用"""
    # 确保加载环境变量
    from dotenv import load_dotenv
    load_dotenv()
    
    app = Flask(__name__)
    
    # 配置
    app.config['ADMIN_USERNAME'] = os.getenv('ADMIN_USERNAME', 'admin')
    app.config['ADMIN_PASSWORD'] = os.getenv('ADMIN_PASSWORD', 'admin')
    app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'your-secret-key-change-in-production')
    
    # 创建数据库表
    Base.metadata.create_all(bind=engine)
    
    # 注册模板过滤器
    @app.template_filter('country_name')
    def country_name_filter(country_code):
        """模板过滤器：将国家代码转换为中文国家名称"""
        return get_country_name(country_code)
    
    @app.template_filter('format_phone')
    def format_phone_filter(phone, country_code):
        """模板过滤器：格式化手机号为国际格式"""
        return format_phone_number(phone, country_code)
    
    @app.template_filter('format_phone_no_prefix')
    def format_phone_no_prefix_filter(phone, country_code):
        """模板过滤器：格式化手机号但不显示国家区号"""
        return format_phone_number_without_prefix(phone, country_code)
    
    @app.template_filter('from_json')
    def from_json_filter(json_string):
        """模板过滤器：将JSON字符串解析为对象"""
        try:
            return json.loads(json_string)
        except Exception:
            return []
    
    # 添加登录路由
    @app.route('/login', methods=['GET', 'POST'])
    def login():
        if request.method == 'POST':
            try:
                username = request.form['username']
                password = request.form['password']
                
                # 获取next参数，用于登录后跳转
                next_page = request.args.get('next') or request.form.get('next')
                
                # 首先检查是否为环境变量中的超级管理员账户
                admin_username = app.config.get('ADMIN_USERNAME', 'admin')
                admin_password = app.config.get('ADMIN_PASSWORD', 'admin')
                
                if username == admin_username and password == admin_password:
                    # 创建一个临时的root用户对象用于会话
                    class TempUser:
                        def __init__(self):
                            self.id = 0
                            self.username = username
                            self.role = "root"
                            self.country = None
                            import datetime as dt
                            self.last_login = dt.datetime.now(dt.UTC)
                    
                    user = TempUser()
                    session['user_id'] = 0  # 使用0作为超级管理员的特殊ID
                    
                    # 对于Ajax请求，返回JSON响应
                    if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                        return jsonify({
                            'success': True,
                            'message': '登录成功',
                            'show_redirect_modal': True
                        })
                    else:
                        # 对于普通请求，设置会话标记并重定向到next页面或默认页面
                        session['show_redirect_modal'] = True
                        if next_page:
                            # 确保next_page是相对路径，防止开放重定向漏洞
                            if next_page.startswith('/'):
                                return redirect(next_page)
                            else:
                                # 如果不是相对路径，重定向到首页
                                return redirect(url_for('home'))
                        else:
                            return redirect(url_for('login'))
                else:
                    # 对于非超级管理员用户，使用数据库验证
                    from controllers.user_auth import authenticate_user
                    user = authenticate_user(username, password)
                    if user:
                        session['user_id'] = user.id
                        # 更新最后登录时间（仅对数据库用户）
                        if hasattr(user, 'last_login'):  # 检查是否为数据库用户
                            db = SessionLocal()
                            try:
                                db_user = db.query(User).filter(User.id == user.id).first()
                                if db_user:
                                    import datetime as dt
                                    db_user.last_login = dt.datetime.now(dt.UTC)
                                    db.commit()
                            except Exception as e:
                                print(f"Error updating last login time: {e}")
                                db.rollback()
                            finally:
                                db.close()
                        
                        # 对于Ajax请求，返回JSON响应
                        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                            return jsonify({
                                'success': True,
                                'message': '登录成功',
                                'show_redirect_modal': True
                            })
                        else:
                            # 对于普通请求，设置会话标记并重定向到next页面或默认页面
                            session['show_redirect_modal'] = True
                            if next_page:
                                # 确保next_page是相对路径，防止开放重定向漏洞
                                if next_page.startswith('/'):
                                    return redirect(next_page)
                                else:
                                    # 如果不是相对路径，重定向到首页
                                    return redirect(url_for('home'))
                            else:
                                return redirect(url_for('login'))
                    else:
                        # 登录失败
                        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                            return jsonify({
                                'success': False,
                                'message': '用户名或密码错误'
                            }), 401
                        else:
                            return render_template('login.html', error='用户名或密码错误', next=next_page)
            except Exception as e:
                print(f"Login error: {e}")
                # 处理异常
                if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                    return jsonify({
                        'success': False,
                        'message': '登录时发生错误，请重试'
                    }), 500
                else:
                    next_page = request.args.get('next') or request.form.get('next')
                    return render_template('login.html', error='登录时发生错误，请重试', next=next_page)
        
        # GET请求 - 显示登录页面
        # 获取next参数
        next_page = request.args.get('next')
        # 获取Bing每日一图
        bing_image_url = get_bing_daily_image()
        show_modal = session.pop('show_redirect_modal', False) if session else False
        return render_template('login.html', show_redirect_modal=show_modal, bing_image_url=bing_image_url, next=next_page)

    @app.route('/logout')
    def logout():
        session.clear()
        return redirect(url_for('login'))
    
    # 添加robots.txt路由
    @app.route('/robots.txt')
    def robots_txt():
        return "User-agent: *\nDisallow: /", 200, {'Content-Type': 'text/plain'}
    
    # 添加主页路由
    @app.route('/')
    def home():
        # 检查用户是否已登录
        if 'user_id' not in session:
            # 未登录，显示公共首页
            db = SessionLocal()
            try:
                # 获取订单统计信息（公开数据）
                query = db.query(Order)
                
                # 获取订单总数
                total_orders = query.count()
                
                # 获取最近7天的订单数
                from datetime import datetime, timedelta
                import datetime as dt
                seven_days_ago = dt.datetime.now(dt.UTC) - timedelta(days=7)
                recent_orders = query.filter(Order.order_date >= seven_days_ago).count()
                
                # 获取客户总数（基于唯一邮箱）
                unique_customers = db.query(Order.customer_email).filter(
                    Order.customer_email.isnot(None)
                ).distinct().count()
                
                # 获取所有成交商品数量（已完成和已发货的订单）
                completed_orders_query = query.filter(Order.status.in_(['completed', 'on-hold']))
                completed_orders = completed_orders_query.all()
                total_items_sold = sum(order.item_count for order in completed_orders)
                
                # 获取状态统计数据（包含所有状态，包括trash）
                from sqlalchemy import func
                status_stats_query = db.query(Order.status, func.count(Order.id).label('count')).group_by(Order.status).order_by(func.count(Order.id).desc())
                status_stats_result = status_stats_query.all()
                
                # 确保所有状态都包含在统计中，即使计数为0
                all_statuses = ['processing', 'completed', 'on-hold', 'cancelled', 'refunded', 'failed']
                status_stats_dict = {}
                
                # 初始化所有状态计数为0
                for status in all_statuses:
                    status_stats_dict[status] = 0
                
                # 填充实际的统计数据
                for stat in status_stats_result:
                    status_stats_dict[stat.status] = stat.count
                    
                # 转换为列表格式以保持与模板的兼容性
                status_stats = []
                for status in all_statuses:
                    status_stats.append({
                        'status': status,
                        'count': status_stats_dict[status]
                    })
                
                # 获取待处理订单数（processing状态）
                pending_orders = query.filter(Order.status == 'processing').count()
                
                # 获取最近一周的订单（增加到100条）
                recent_orders_list = query.filter(Order.order_date >= seven_days_ago).order_by(Order.order_date.desc()).limit(100).all()
                                
                for order in recent_orders_list:
                    # 提取运单物流数据
                    tracking_data = []
                    order_items = []

                    if order.item_details:
                        try:
                            import json
                            from collections import defaultdict

                            items = json.loads(order.item_details)

                            # 使用字典来合计同一商品的数量
                            item_summary = defaultdict(lambda: {'name': '', 'total_quantity': 0, 'meta_data': []})

                            for item in items:
                                # 获取商品ID（使用商品名称作为ID，因为原始数据中可能没有真正的ID）
                                item_id = item.get('name', '') + '_' + str(item.get('id', ''))

                                # 合计数量
                                item_summary[item_id]['name'] = item.get('name', '')
                                item_summary[item_id]['total_quantity'] += item.get('quantity', 0)

                                # 收集口味等元数据（只保留第一次出现的）
                                if 'meta_data' in item and not item_summary[item_id]['meta_data']:
                                    for meta in item['meta_data']:
                                        if meta.get('key') in ['pa_taste', '口味', 'taste', 'pa_flavors', 'flavors', 'pa_flavor', 'flavor', 'pa_smaki', 'smaki', 'pa_smak', 'smak']:
                                            item_summary[item_id]['meta_data'].append({
                                                'key': meta.get('key', ''),
                                                'value': meta.get('value', '')
                                            })

                                # 提取物流信息
                                if 'meta_data' in item:
                                    for meta in item['meta_data']:
                                        if meta.get('key') == '_vi_wot_order_item_tracking_data':
                                            tracking_info = json.loads(meta.get('value', '[]'))
                                            if isinstance(tracking_info, list):
                                                tracking_data.extend(tracking_info)
                                            elif isinstance(tracking_info, dict):
                                                tracking_data.append(tracking_info)

                            # 转换为列表格式
                            for item_id, item_info in item_summary.items():
                                order_items.append({
                                    'name': item_info['name'],
                                    'quantity': item_info['total_quantity'],
                                    'meta_data': item_info['meta_data']
                                })

                        except Exception as e:
                            print(f"解析订单数据时出错: {e}")

                    # 将 tracking_data 和 items 添加到订单对象中
                    order.tracking_data = tracking_data
                    order.items = order_items
                
                return render_template('home.html', 
                                     total_orders=total_orders,
                                     recent_orders=recent_orders,
                                     unique_customers=unique_customers,
                                     status_stats=status_stats,
                                     pending_orders=pending_orders,
                                     total_items_sold=total_items_sold,
                                     recent_orders_list=recent_orders_list,
                                     current_user=None)  # 未登录用户

            except Exception as e:
                return render_template('home.html', error='处理用户权限时出错，请重试')
            finally:
                db.close()

        # 检查是否为环境变量中的超级管理员账户（ID为0）
        if session['user_id'] == 0:
            # 创建一个临时的root用户对象
            class TempUser:
                def __init__(self):
                    self.id = 0
                    self.username = app.config.get('ADMIN_USERNAME', 'admin')
                    self.role = "root"
                    self.country = None
                
                def has_permission(self, required_role, target_country=None):
                    return True
                    
                def can_view_order(self, order_country):
                    return True
                    
                def can_view_customer(self, customer_country):
                    return True
                    
                def can_add_order(self):
                    return True
                    
                def can_add_customer(self):
                    return True
            
            current_user = TempUser()
        else:
            # 从数据库获取用户信息
            db = SessionLocal()
            try:
                user = db.query(User).filter(User.id == session['user_id'], User.is_active == True).first()
                if not user:
                    session.clear()
                    return redirect(url_for('login', next=request.url))
                current_user = user
            finally:
                db.close()
        
        db = SessionLocal()
        try:
            # 获取订单统计信息
            query = db.query(Order)
            
            # 根据用户角色应用过滤
            if current_user and current_user.role == "user" and current_user.country:
                query = query.filter(Order.customer_country == current_user.country)
            elif current_user and current_user.role == "manager":
                # manager可以查看所有国家的订单
                pass
            # root用户可以查看所有订单
            
            # 获取订单总数
            total_orders = query.count()
            
            # 获取最近7天的订单数
            import datetime as dt
            from datetime import timedelta
            seven_days_ago = dt.datetime.now(dt.UTC) - timedelta(days=7)
            recent_orders = query.filter(Order.order_date >= seven_days_ago).count()
            
            # 获取客户总数（基于唯一邮箱）
            unique_customers = db.query(Order.customer_email).filter(
                Order.customer_email.isnot(None)
            ).distinct().count()
            
            # 获取所有成交商品数量（已完成和已发货的订单）
            completed_orders_query = query.filter(Order.status.in_(['completed', 'on-hold']))
            completed_orders = completed_orders_query.all()
            total_items_sold = sum(order.item_count for order in completed_orders)
            
            # 获取状态统计数据（包含所有状态，包括trash）
            from sqlalchemy import func
            status_stats_query = db.query(Order.status, func.count(Order.id).label('count')).group_by(Order.status).order_by(func.count(Order.id).desc())
            if current_user and current_user.role == "user" and current_user.country:
                status_stats_query = status_stats_query.filter(Order.customer_country == current_user.country)
            status_stats_result = status_stats_query.all()
            
            # 确保所有状态都包含在统计中，即使计数为0
            all_statuses = ['processing', 'completed', 'on-hold', 'cancelled', 'refunded', 'failed']
            status_stats_dict = {}
            
            # 初始化所有状态计数为0
            for status in all_statuses:
                status_stats_dict[status] = 0
            
            # 填充实际的统计数据
            for stat in status_stats_result:
                status_stats_dict[stat.status] = stat.count
                
            # 转换为列表格式以保持与模板的兼容性
            status_stats = []
            for status in all_statuses:
                status_stats.append({
                    'status': status,
                    'count': status_stats_dict[status]
                })
            
            # 获取待处理订单数（processing状态）
            pending_orders = query.filter(Order.status == 'processing').count()
            
            # 获取最近一周的订单（增加到100条）
            recent_orders_list = query.filter(Order.order_date >= seven_days_ago).order_by(Order.order_date.desc()).limit(100).all()
            
            # 为每个订单提取物流信息和商品详情
            for order in recent_orders_list:
                tracking_data = []
                order_items = []

                if order.item_details:
                    try:
                        import json
                        from collections import defaultdict

                        items = json.loads(order.item_details)

                        item_summary = defaultdict(lambda: {'name': '', 'total_quantity': 0, 'meta_data': []})

                        for item in items:
                            item_id = item.get('name', '') + '_' + str(item.get('id', ''))
                            item_summary[item_id]['name'] = item.get('name', '')
                            item_summary[item_id]['total_quantity'] += item.get('quantity', 0)

                            if 'meta_data' in item and not item_summary[item_id]['meta_data']:
                                for meta in item['meta_data']:
                                    if meta.get('key') in ['pa_taste', '口味', 'taste', 'pa_flavors', 'flavors', 'pa_flavor', 'flavor', 'pa_smaki', 'smaki', 'pa_smak', 'smak']:
                                        item_summary[item_id]['meta_data'].append({
                                            'key': meta.get('key', ''),
                                            'value': meta.get('value', '')
                                        })

                            if 'meta_data' in item:
                                for meta in item['meta_data']:
                                    if meta.get('key') == '_vi_wot_order_item_tracking_data':
                                        tracking_info = json.loads(meta.get('value', '[]'))
                                        if isinstance(tracking_info, list):
                                            tracking_data.extend(tracking_info)
                                        elif isinstance(tracking_info, dict):
                                            tracking_data.append(tracking_info)

                        for item_id, item_info in item_summary.items():
                            order_items.append({
                                'name': item_info['name'],
                                'quantity': item_info['total_quantity'],
                                'meta_data': item_info['meta_data']
                            })

                    except Exception as e:
                        print(f"解析订单数据时出错: {e}")

                order.tracking_data = tracking_data
                order.items = order_items

            
            return render_template('home.html', 
                                 total_orders=total_orders,
                                 recent_orders=recent_orders,
                                 unique_customers=unique_customers,
                                 status_stats=status_stats,
                                 pending_orders=pending_orders,  # 添加待处理订单数
                                 total_items_sold=total_items_sold,  # 添加成交商品总数
                                 recent_orders_list=recent_orders_list,
                                 current_user=current_user)
        finally:
            db.close()
    
    # 注册控制器
    order_controller = OrderController(app)
    customer_controller = CustomerController(app)
    api_controller = APIController(app)
    user_controller = UserController(app)  # 注册用户控制器
    
    return app

def should_sync_orders():
    """判断是否应该同步订单数据"""
    # 检查环境变量是否禁用启动时同步
    if os.getenv('SYNC_ON_STARTUP', 'true').lower() == 'false':
        return False
    
    # 检查是否存在上次同步时间记录文件
    if not os.path.exists(LAST_SYNC_FILE):
        return True
    
    # 读取上次同步时间
    try:
        with open(LAST_SYNC_FILE, 'r') as f:
            last_sync_str = f.read().strip()
            last_sync = datetime.fromisoformat(last_sync_str)
            
            # 如果距离上次同步超过1小时，则再次同步
            sync_interval = int(os.getenv('SYNC_INTERVAL_HOURS', '1'))
            if datetime.now() - last_sync > timedelta(hours=sync_interval):
                return True
            else:
                return False
    except Exception:
        # 如果读取或解析失败，默认进行同步
        return True

def record_sync_time():
    """记录同步时间"""
    try:
        with open(LAST_SYNC_FILE, 'w') as f:
            f.write(datetime.now().isoformat())
    except Exception as e:
        print(f"记录同步时间失败: {e}")

def sync_orders_on_startup():
    """应用启动时同步订单数据"""
    try:
        # 检查是否需要同步
        if not should_sync_orders():
            print("ℹ️  根据配置跳过启动时订单同步")
            return
            
        print("🔄 应用启动时自动同步订单数据...")
        sync_stats = sync_all()
        print(f"✅ 订单数据同步完成！新增 {sync_stats['inserted']} 个订单，更新 {sync_stats['updated']} 个订单")
        
        # 记录同步时间
        record_sync_time()
    except Exception as e:
        print(f"❌ 启动时同步订单数据失败: {e}")

# 创建应用实例
app = create_app()

def init_users():
    """初始化默认用户"""
    # 初始化数据库表
    init_db()
    
    # 删除默认用户创建逻辑
    pass

if __name__ == '__main__':
    init_db()
    print("✅ 数据库表已创建")
    
    # 检查是否需要启动时同步 - 设置为False以跳过同步
    sync_on_startup = False  # os.getenv('SYNC_ON_STARTUP', 'true').lower() != 'false'
    if sync_on_startup:
        sync_stats = sync_all()
        print(f"✅ 订单数据同步完成！新增 {sync_stats['inserted']} 个订单，更新 {sync_stats['updated']} 个订单")
    else:
        print("ℹ️  根据配置跳过启动时订单同步")
    
    # 从环境变量读取端口配置，默认为39500
    import os
    port = int(os.environ.get('PORT', 39500))
    app.run(host='0.0.0.0', port=port, debug=False)
